import logging
from controllers.errors.online_mall.brand_errors import HProdBrandNotFoundError, HProdBrandParamError
from core.entities.account_role import AccountWrap
from extensions.ext_database import db
from flask_babel import _
from werkzeug.exceptions import InternalServerError
from models.online_mall.prod_category import MBrand, MCategoryBrand
from services.file_service import FileService

class ProdBrandService:
    @staticmethod
    def get_brand_list(account:AccountWrap,args:dict)->dict:
        try:
            query = db.session.query(MBrand).filter(MBrand.tenant_id==account.current_tenant_id)
            total = 0
            has_more = False
            if 'id' in args and args['id']:
                query = query.filter(MBrand.id==args['id'])
                total = query.count()
            else:
                if 'name' in args and args['name']:
                    query = query.filter(MBrand.name.like(f"%{args['name']}%"))
                if 'brief' in args and args['brief']:
                    query = query.filter(MBrand.brief.ilike(f"%{args['brief']}%"))
                if 'content' in args and args['content']:
                    query = query.filter(MBrand.content.ilike(f"%{args['content']}%"))
                if 'first_char' in args and args['first_char']:
                    query = query.filter(MBrand.first_char==args['first_char'])
                total = query.count()
                if 'page' in args and args['page']>0 and 'page_size' in args and args['page_size']>0:
                    query = query.offset((args['page']-1)*args['page_size']).limit(args['page_size'])
                    has_more = total > args['page']*args['page_size']
            data = query.order_by(MBrand.seq.desc()).all()
            return {
                "total":total,
                "has_more":has_more,
                "data":data
            }
        except Exception as e:
            logging.error(e)
            return {
                "total":0,
                "has_more":False,
                "data":[],
                "message":str(e)
            }
        
    @staticmethod
    def _next_brand_seq(tenant_id)->int:
        next_seq = db.session.query(MBrand.seq).filter(MBrand.tenant_id==tenant_id).order_by(MBrand.seq.desc()).scalar()
        return 1 if not next_seq else next_seq + 1
    
    @staticmethod
    def create_brand(account:AccountWrap,args:dict)->MBrand:
        if not account or not isinstance(account,AccountWrap):
            raise NotLoginError()
        brand = MBrand(
            tenant_id = account.current_tenant_id, # type: ignore
            created_by = account.id #type: ignore
            )
        
        next_seq = ProdBrandService._next_brand_seq(account.current_tenant_id)
        args['seq'] = next_seq
        
        ProdBrandService._fill_brand_param(args, brand)
        try:
            db.session.add(brand)
            db.session.commit()
            return brand
        except Exception as e:
            db.session.rollback()
            raise InternalServerError(str(e))

    @staticmethod
    def update_brand(account:AccountWrap,args:dict)->MBrand:
        if not account or not isinstance(account,AccountWrap):
            raise NotLoginError()
        brand_id = args.get('id')
        if not brand_id:
            raise HProdBrandNotFoundError(brand_id)
        brand = db.session.get(MBrand,brand_id)
        if not brand:
            raise HProdBrandNotFoundError(brand_id)
        
        ProdBrandService._fill_brand_param(args, brand)
        try:

            db.session.commit()
            return brand
        except Exception as e:
            db.session.rollback()
            raise InternalServerError(str(e))
        
    @staticmethod
    def delete_brand(account:AccountWrap,brand_id)->MBrand:
        if not account or not isinstance(account,AccountWrap):
            raise NotLoginError()
        if not brand_id:
            raise HProdBrandNotFoundError(brand_id)
        brand = db.session.get(MBrand,brand_id)
        if not brand:
            raise HProdBrandNotFoundError(brand_id)
        
        try:
            db.session.delete(brand)
            db.session.query(MCategoryBrand).filter(MCategoryBrand.brand_id==brand_id).delete()
            db.session.commit()
            return brand
        except Exception as e:
            db.session.rollback()
            raise InternalServerError(str(e))
    @staticmethod
    def _fill_brand_param(args:dict, brand:MBrand):
        if 'name' in args and args['name']:
            brand.name = args['name']
        else:
            raise HProdBrandParamError(_("Brand name can not be empty"))
        
        if 'pic_file_id' in args and args['pic_file_id']:
            brand.pic_file_id = args['pic_file_id']
            if not FileService.file_exist(brand.pic_file_id):
                raise HProdBrandParamError(_("Pic File does not exist."))
        
        if 'memo' in args and args['memo']:
            brand.memo = args['memo']

        if 'seq' in args and args['seq']:
            brand.seq = args['seq']

        if 'status' in args and args['status'] is not None:
            brand.status = args['status']

        if 'brief' in args and args['brief']:
            brand.brief = args['brief']

        if 'content' in args and args['content']:
            brand.content = args['content']

        if 'first_char' in args and args['first_char']:
            if len(args['first_char']) > 1:
                raise HProdBrandParamError(_("The first_char length must be 1"))
            brand.first_char = args['first_char']

        